package com.hd.trans.extension

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hd.trans.share.Md5Util
import com.hd.trans.utils.LogUtil
import okhttp3.Headers
import java.math.BigDecimal
import java.util.TreeMap


fun <T> Gson.typedToJson(src: T): String = toJson(src)

inline fun <reified T : Any> Gson.fromJson(json: String): T =
    fromJson(json, object : TypeToken<T>() {}.type)

/**
 * 生成数据签名
 * 加密方法：md5摘要；
 * 结果：32位小写字符串
 * 方法： 将json中除datasign外的其它所有的参数(包含公共参数 和 其它非公共参数) ，按参数名称的字母排序,如：a=1&b=2&c=3，组合为：a=1&b=2&c=3hUuPd20171206LuOnDmd5加密，其中 hUuPd20171206LuOnD 为 校验码，32位小写 待加密的字符串中，空值不参与加密；
 * 支付接口 payorer 加密时 因为 在payorderparm中 prouctid加密处理过，所以 待加密中 productid 不再参与；
 * 加密结果以 datasign加入json中，如： {"a":1,"b":2,"c":"3","datasign":"ff7f0c6f941f353e43a509cd0ddd048c"}
 * 若该字段为空或为null, 不建议在请求参数中再使用该字段
 * 每个请求参数字段, 需要提前去除开头与结尾的空格与换行等特殊字符, 再发起请求
 * @param excludeSet 排除的参数
 * @param headers http请求头，如果请求头不为空则将参数加到请求头中
 */
fun TreeMap<String, Any>.dataSign(excludeSet:HashSet<String>? = null,headers: Headers.Builder? = null):String {
    val jsonBuild = StringBuilder()
    this.forEach {
        if (it.key.isEmpty())
            return@forEach
        if ("" == it.value)
            return@forEach
        val isExclude = excludeSet?.contains(it.key) ?: false
        if (!isExclude){
            val value = toJson(it.value).toString().trim()
            jsonBuild.append("&").append(it.key).append("=").append(value)
            headers?.add(it.key, value)
        }
    }
    jsonBuild.deleteCharAt(0)
    jsonBuild.append("hUuPd20171206LuOnD")
    val sign_wait = jsonBuild.toString()
    LogUtil.d("sign_wait:`${sign_wait}`")
    return Md5Util.md5(sign_wait)
}

fun toJson(data: Any): Any {
    return when (data) {
        is Long -> data
        is String -> data
        is Int -> data
        is Boolean -> data
        is Float,is Double -> {
            //用正则删除小数点后面的0 [.]*0+$
            val numStr = data.toString().replace("[.]*0+$".toRegex(), "")
            val bigDecimal = BigDecimal(numStr)
            if(numStr.contains('.')){
                bigDecimal.toFloat()
            }
            else{
                bigDecimal.toInt()
            }
        }
        else -> gson.toJson(data)
    }
}